﻿using CommonLib.LogOperation;
using DispatchingCenter.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace DispatchingCenter.Dispatch
{
    /// <summary>
    /// 调度器
    /// </summary>
    public class Dispatcher
    {
        /// <summary>
        /// 调度关系网
        /// </summary>
        private static Dictionary<Type, List<DispatchHandlerAttribute>> _dicDispatchRelativeNetwork = new Dictionary<Type, List<DispatchHandlerAttribute>>();

        /// <summary>
        /// 激活前处理器列表
        /// </summary>
        private static List<DispatchHandlerAttribute> _lstBeforeActiveHandler = new List<DispatchHandlerAttribute>();

        /// <summary>
        /// 建立调度关系网
        /// </summary>
        /// <param name="assembly"></param>
        public static void BuildDispatchRelationship(Assembly assembly)
        {
            Logger.Info("调度器：开始建立调度关系网...");

            var types = assembly.GetTypes();

            foreach (var type in types)
            {
                var methods = type.GetMethods();

                foreach (var method in methods)
                {
                    var attribute = method.GetCustomAttributes(typeof(DispatchHandlerAttribute), true).FirstOrDefault();
                    if (attribute != null)
                    {
                        CheckParameterRule(method);

                        var handler = attribute as DispatchHandlerAttribute;
                        handler.DispatchInstance = Activator.CreateInstance(type);
                        handler.ActionMethodInfo = method;

                        if (attribute is DispatchBeforeActiveHandlerAttribute)
                        {
                            AddBeforeActiveHandler(handler);
                        }
                        else
                        {
                            AddDispatchRelation(handler);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 添加激活前处理器
        /// </summary>
        /// <param name="handler">调度处理器</param>
        private static void AddBeforeActiveHandler(DispatchHandlerAttribute handler)
        {
            _lstBeforeActiveHandler.Add(handler);

            Logger.Info(string.Format("调度器：增加激活前处理器 [{0}]-[{1}.{2}]", handler.ObservedDispatchEventType.Name, handler.DispatchInstance.GetType().Name, handler.ActionMethodInfo.Name));
        }

        /// <summary>
        /// 添加调度关系
        /// </summary>
        /// <param name="handler">调度处理器</param>
        private static void AddDispatchRelation(DispatchHandlerAttribute handler)
        {
            var eventType = handler.ObservedDispatchEventType;

            if (!_dicDispatchRelativeNetwork.ContainsKey(eventType))
            {
                _dicDispatchRelativeNetwork.Add(eventType, new List<DispatchHandlerAttribute>());
            }

            _dicDispatchRelativeNetwork[eventType].Add(handler);

            Logger.Info(string.Format("调度器：建立新的关系网 [{0}]-[{1}.{2}]", eventType.Name, handler.DispatchInstance.GetType().Name, handler.ActionMethodInfo.Name));
        }

        /// <summary>
        /// 检查参数规则
        /// </summary>
        /// <param name="method"></param>
        private static void CheckParameterRule(MethodInfo method)
        {
            var parameters = method.GetParameters();
            if (parameters == null ||
                parameters.Length != 1 ||
                (!parameters.FirstOrDefault().ParameterType.Equals(typeof(DispatchEvent)) &&
                 !parameters.FirstOrDefault().ParameterType.BaseType.Equals(typeof(DispatchEvent))
                ))
            {
                throw new Exception(string.Format("DispatchHandler - [{0}]的参数必须是只有一个且继承自DispatchEvent", method.Name));
            }
        }

        /// <summary>
        /// 激活事件
        /// </summary>
        /// <param name="dispatchEvent">调度事件</param>
        public static void ActiveEvent(DispatchEvent dispatchEvent)
        {
            var type = dispatchEvent.GetType();

            if (!_dicDispatchRelativeNetwork.ContainsKey(type))
            {
                Logger.Error(string.Format("调度器：当前事件[{0}]没有找到绑定的Handler", type.FullName));
                return;
            }

            _lstBeforeActiveHandler.ForEach(action =>
            {
                ActiveAction(action, dispatchEvent);
            });

            _dicDispatchRelativeNetwork[type].ForEach(action =>
            {
                ActiveAction(action, dispatchEvent);
            });
        }

        private static void ActiveAction(DispatchHandlerAttribute action, DispatchEvent dispatchEvent)
        {
            try
            {
                action.ActionMethodInfo.Invoke(action.DispatchInstance, new object[] { dispatchEvent });
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null && ex.InnerException.GetType().Equals(typeof(WCFLib.ExceptionExtension.GException)))
                {
                    throw ex.InnerException;
                }
                else
                {
                    throw;
                }
            }
        }
    }
}
